package com.tengju.bff.interfaces.covercharge.service.impl;

import com.aliyun.oss.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.tengju.bff.interfaces.covercharge.constant.*;
import com.tengju.bff.interfaces.covercharge.entity.dto.WithdrawalApplyInfo;
import com.tengju.bff.interfaces.covercharge.entity.model.SmsVerification;
import com.tengju.bff.interfaces.covercharge.entity.po.*;
import com.tengju.bff.interfaces.covercharge.entity.vo.*;
import com.tengju.bff.interfaces.covercharge.entity.vo.contract.ApplyCertificateReqVo;
import com.tengju.bff.interfaces.covercharge.entity.vo.contract.CompanyCertApplyVo;
import com.tengju.bff.interfaces.covercharge.entity.vo.contract.PersonCertApplyVo;
import com.tengju.bff.interfaces.covercharge.entity.vo.contract.SignContractReqVo;
import com.tengju.bff.interfaces.covercharge.enums.ProfitTypeEnum;
import com.tengju.bff.interfaces.covercharge.handler.CoverChargeException;
import com.tengju.bff.interfaces.covercharge.mapper.ServiceSelfCertificationMapper;
import com.tengju.bff.interfaces.covercharge.service.*;
import com.tengju.bff.interfaces.covercharge.service.bestsign.impl.auth.BestSignAuthService;
import com.tengju.bff.interfaces.covercharge.service.message.client.UserMessageClient;
import com.tengju.bff.interfaces.covercharge.util.DateTimeUtils;
import com.tengju.bff.interfaces.covercharge.util.UserUtils;
import com.tengju.payment.domain.shard.JsonUtil;
import com.tengju.settlement.domain.model.account.UserIdCode;
import com.tengju.settlement.domain.model.depository.*;
import com.tengju.user.application.login.SmsVerifyCodeService;
import com.tengju.user.application.shared.ApplicationException;
import com.tengju.user.application.shared.ApplicationExceptionCode;
import com.tengju.user.domain.model.archive.sign.SignFromEnum;
import com.tengju.user.domain.model.login.UserType;
import com.tengju.user.domain.model.sms.ManMachineValidateData;
import com.tengju.user.domain.model.sms.OperationType;
import com.tengju.user.domain.model.sms.SendSmsVerifyCodeData;
import com.tengju.user.domain.service.SmsBaseService;
import com.zoi7.component.core.util.MD5Utils;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 自认证服务实现类
 * </p>
 *
 * @author zhaoyi
 * @since 2020-02-24
 */
@Service
@Slf4j
public class SelfCertificationServiceImpl implements SelfCertificationService {

    @Autowired
    @Lazy
    private IServiceSignService serviceSignService;

    @Autowired
    private IServiceAccountService serviceAccountService;

    @Autowired
    private IServiceSelfCertificationService serviceSelfCertificationService;

    @Autowired
    private IServiceSelfCertificationWithdrawService serviceSelfCertificationWithdrawService;

    @Autowired
    @Lazy
    private LeTaxOneServiceImpl leTaxOneServiceImpl;

    @Autowired
    private IServiceLetaxWithdrawLogService serviceLetaxWithdrawLogService;

    @Autowired
    private IServiceLetaxRegisteredReturnService serviceLetaxRegisteredReturnService;

    @Autowired
    private ServiceSelfCertificationMapper serviceSelfCertificationMapper;

    @Autowired
    private IAttachmentService attachmentService;

    @Autowired
    private IServiceBankService serviceBankService;

    @Autowired
    private IServiceLetaxRegisteredService serviceLetaxRegisteredService;

    @Autowired
    private UserMessageClient userMessageClient;

    @Autowired
    private BestSignAuthService authService;

    @Autowired
    private IMemberService memberService;

    @Autowired
    private IServiceContractService serviceContractService;

    @Autowired
    private IServiceSignRecordService serviceSignRecordService;

    @Autowired
    private SmsBaseService smsBaseService;

    @Autowired
    private SmsVerifyCodeService smsVerifyCodeService;
    @Autowired
    private DepositoryAccountRepository depositoryAccountRepository;
    @Autowired
    private DepositoryBankCardRepository depositoryBankCardRepository;

    /**
     * 自认证提现申请
     *
     * @param accountType            账户类型
     * @param idCode                 idCode
     * @param withdrawalCompanyApply 自认证申请信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer withdrawalApply(CoverChargeEnum.ServiceAccountType accountType, Integer idCode, WithdrawalCompanyApply withdrawalCompanyApply, DepositoryAccount depositoryAccount) {
        ServiceSign serviceSignParam = new ServiceSign();
        serviceSignParam.setIdCode(idCode);
        serviceSignParam.setPlatformCode(accountType.getPlatform());
        ServiceSign serviceSign = serviceSignService.getOne(new QueryWrapper<>(serviceSignParam));
        // 判断是否签约
        Assert.isTrue(serviceSign != null && CoverChargeEnum.CommonStatus.YES.getName().equals(serviceSign.getIsSigned()), "未签约");
        Assert.isTrue(SignIdentityEnum.certified_individual.toString().equals(serviceSign.getCurrentIdentity())
                || SignIdentityEnum.certified_business.toString().equals(serviceSign.getCurrentIdentity()), "当前身份不正确");

        ServiceAccount serviceAccount = serviceAccountService.getAccount(accountType.getCode(), idCode);
        BigDecimal balance = serviceAccount.getBalance() != null ? serviceAccount.getBalance() : BigDecimal.ZERO;
        BigDecimal money = withdrawalCompanyApply.getMoney();
        Assert.isTrue(money.compareTo(balance) <= 0, "可提现余额不足");

        Integer accountId = serviceAccount.getId();

        ServiceSelfCertification serviceSelfCertificationParam = new ServiceSelfCertification();
        serviceSelfCertificationParam.setStatus(CoverChargeEnum.AuthStatus.PASS.getCode());
        serviceSelfCertificationParam.setIdCode(idCode);
        serviceSelfCertificationParam.setAccountId(accountId);
        ServiceSelfCertification serviceSelfCertification = serviceSelfCertificationService.getOne(new QueryWrapper<>(serviceSelfCertificationParam));
        Assert.notNull(serviceSelfCertification, "未自认证企业或个体工商户");

        List<DepositoryBankCard> depositoryBankCards = depositoryBankCardRepository
                .getByDepositoryAccountIdStatus(new UserIdCode(idCode), depositoryAccount.getDepositoryAccountId(), List.of(BindStatus.SUCCESS));
        if (CollectionUtils.isEmpty(depositoryBankCards)) {
            throw ApplicationException.error(ApplicationExceptionCode.DEP_BAND_CARD_NOT_BOUND);
        }

        ServiceSelfCertificationWithdraw selfCertificationWithdraw = new ServiceSelfCertificationWithdraw();
        selfCertificationWithdraw.setIdCode(idCode);
        selfCertificationWithdraw.setAccountId(accountId);
        selfCertificationWithdraw.setBankNo(depositoryBankCards.get(0).getCardNo());
        selfCertificationWithdraw.setMoney(money);
        selfCertificationWithdraw.setInvoice(withdrawalCompanyApply.getInvoice());
        selfCertificationWithdraw.setInvoiceImg(withdrawalCompanyApply.getInvoiceImg());
        selfCertificationWithdraw.setSelfCertificationId(serviceSelfCertification.getId());
        selfCertificationWithdraw.setType(serviceSelfCertification.getType());
        selfCertificationWithdraw.setStatus(SelfWithdrawStatusEnum.APPLY.getCode());
        selfCertificationWithdraw.setRemark("等待审核");
        //平台编号
        selfCertificationWithdraw.setPlatformCode(accountType.getPlatform());
        selfCertificationWithdraw.setApplyRemark(withdrawalCompanyApply.getApplyRemark());
        selfCertificationWithdraw.setReason(withdrawalCompanyApply.getReason() != null ? withdrawalCompanyApply.getReason() : 0);
        selfCertificationWithdraw.setReasonNew(withdrawalCompanyApply.getReason_new());
        selfCertificationWithdraw.setCardHolder(serviceSelfCertification.getCardHolder());
        selfCertificationWithdraw.setCreatedAt(LocalDateTime.now());
        SelfCertificationWithdrawExtra extra = new SelfCertificationWithdrawExtra(depositoryAccount.getDepositoryChannel());
        selfCertificationWithdraw.setExtra(JsonUtil.toJSONString(extra));
        serviceSelfCertificationWithdrawService.save(selfCertificationWithdraw);

        // 冻结金额
        serviceAccountService.freezeBalance(accountType.getCode(), idCode, ProfitTypeEnum.self_withdraw, money, selfCertificationWithdraw.getId(), null);

        return selfCertificationWithdraw.getId();
    }

    /**
     * 自认证重新申请
     *
     * @param idCode                   idCode
     * @param withdrawalCompanyReApply 自认证重新申请信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer withdrawalApplyUpdate(Integer idCode, WithdrawalCompanyReApply withdrawalCompanyReApply) {
        ServiceSelfCertificationWithdraw certificationWithdraw = serviceSelfCertificationWithdrawService.getById(withdrawalCompanyReApply.getId());
        Assert.notNull(certificationWithdraw, "没有找到该条申请记录");
        Assert.isTrue(idCode.equals(certificationWithdraw.getIdCode()), "用户不一致");
        Assert.isTrue(SelfWithdrawStatusEnum.FREJECT.getCode().equals(certificationWithdraw.getStatus())
                || SelfWithdrawStatusEnum.SREJECT.getCode().equals(certificationWithdraw.getStatus()), "该申请不符合重新提交条件");

        ServiceSelfCertificationWithdraw selfCertificationWithdrawUp = new ServiceSelfCertificationWithdraw();
        selfCertificationWithdrawUp.setId(withdrawalCompanyReApply.getId());
        selfCertificationWithdrawUp.setInvoice(withdrawalCompanyReApply.getInvoice());
        selfCertificationWithdrawUp.setInvoiceImg(withdrawalCompanyReApply.getInvoiceImg());
        selfCertificationWithdrawUp.setStatus(SelfWithdrawStatusEnum.APPLY.getCode());
        selfCertificationWithdrawUp.setRemark("重新提交等待审核");
        selfCertificationWithdrawUp.setReason(withdrawalCompanyReApply.getReason());
        selfCertificationWithdrawUp.setReasonNew(withdrawalCompanyReApply.getReason_new());
        selfCertificationWithdrawUp.setApplyRemark(withdrawalCompanyReApply.getApplyRemark());
        selfCertificationWithdrawUp.setUpdatedAt(LocalDateTime.now());
        serviceSelfCertificationWithdrawService.updateById(selfCertificationWithdrawUp);

        return certificationWithdraw.getId();
    }

    /**
     * 自认证提现申请取消
     *
     * @param idCode       idCode
     * @param platformCode 平台编号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void withdrawalApplyCancel(Integer idCode, String platformCode, Integer applyId) {
        Integer accountType = null;
        if (CoverChargeEnum.ServiceAccountType.MANAGE_TYPE.getPlatform().equals(platformCode)) {
            accountType = CoverChargeEnum.ServiceAccountType.MANAGE_TYPE.getCode();
        }
        Assert.notNull(accountType, "账户类型不正确");

        List<ServiceSelfCertificationWithdraw> selfCertificationWithdrawList = null;
        if (applyId == null) {
            ServiceSelfCertificationWithdraw selfCertificationWithdrawParam = new ServiceSelfCertificationWithdraw();
            selfCertificationWithdrawParam.setIdCode(idCode);
            selfCertificationWithdrawParam.setPlatformCode(platformCode);
            selfCertificationWithdrawParam.setStatus(SelfWithdrawStatusEnum.APPLY.getCode());
            selfCertificationWithdrawList = serviceSelfCertificationWithdrawService.list(new QueryWrapper<>(selfCertificationWithdrawParam));
        } else {
            selfCertificationWithdrawList = new ArrayList<>();
            ServiceSelfCertificationWithdraw selfCertificationWithdraw = serviceSelfCertificationWithdrawService.getById(applyId);
            Assert.notNull(selfCertificationWithdraw, "升级过程中不能操作取消，请联系管家取消");

            Assert.isTrue(SelfWithdrawStatusEnum.APPLY.getCode().equals(selfCertificationWithdraw.getStatus())
                    || SelfWithdrawStatusEnum.FPASS.getCode().equals(selfCertificationWithdraw.getStatus())
                    || SelfWithdrawStatusEnum.FREJECT.getCode().equals(selfCertificationWithdraw.getStatus())
                    || SelfWithdrawStatusEnum.SREJECT.getCode().equals(selfCertificationWithdraw.getStatus()), "申请状态不正确");
            selfCertificationWithdrawList.add(selfCertificationWithdraw);
        }

        List<ServiceSelfCertificationWithdraw> updateList = new ArrayList<>();
        BigDecimal totalMoney = BigDecimal.ZERO;
        List<WithdrawalApplyInfo> withdrawalApplyInfoList = new ArrayList<>();
        for (ServiceSelfCertificationWithdraw selfCertificationWithdraw : selfCertificationWithdrawList) {
            totalMoney = totalMoney.add(selfCertificationWithdraw.getMoney());

            ServiceSelfCertificationWithdraw selfCertificationWithdrawUp = new ServiceSelfCertificationWithdraw();
            selfCertificationWithdrawUp.setId(selfCertificationWithdraw.getId());
            selfCertificationWithdrawUp.setStatus(SelfWithdrawStatusEnum.CANCEL.getCode());
            updateList.add(selfCertificationWithdrawUp);

            WithdrawalApplyInfo withdrawalApplyInfo = new WithdrawalApplyInfo();
            withdrawalApplyInfo.setApplyMoney(selfCertificationWithdraw.getMoney());
            withdrawalApplyInfo.setBizId(selfCertificationWithdraw.getId());
            withdrawalApplyInfoList.add(withdrawalApplyInfo);
        }

        //更新提现申请表
        updateList.forEach(serviceSelfCertificationWithdraw -> {

            boolean updateLog = serviceSelfCertificationWithdrawService.updateById(serviceSelfCertificationWithdraw);
            Assert.isTrue(updateLog, "提现记录变更失败");


        });

        //serviceSelfCertificationWithdrawService.updateBatchById(updateList);

        serviceAccountService.unFreezeBalance(accountType, idCode, ProfitTypeEnum.self_withdraw, totalMoney, withdrawalApplyInfoList);
    }

    /**
     * 个体提现申请理由修改
     *
     * @param idCode          代理id
     * @param platformCode    平台编码
     * @param withdrawalApply withdrawalApply
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer updateApplyReason(Integer idCode, String platformCode, WithdrawalApply withdrawalApply, String beforeIdentity) {

        //查找自认证提现
        ServiceSelfCertificationWithdraw selfCertificationWithdrawUp = new ServiceSelfCertificationWithdraw();
        selfCertificationWithdrawUp.setId(withdrawalApply.getId());
        ServiceSelfCertificationWithdraw serviceSelfCertificationWithdraw = serviceSelfCertificationWithdrawService.getOne(new QueryWrapper<>(selfCertificationWithdrawUp));

        //如果记录为空或者提现idCode不相等
        if (Objects.isNull(serviceSelfCertificationWithdraw) || !serviceSelfCertificationWithdraw.getIdCode().equals(idCode)) {
            //查找乐税提现
            ServiceLetaxWithdrawLog letaxWithdrawLogParam = new ServiceLetaxWithdrawLog();
            letaxWithdrawLogParam.setId(withdrawalApply.getId());
            ServiceLetaxWithdrawLog serviceLetaxWithdrawLog = serviceLetaxWithdrawLogService.getOne(new QueryWrapper<>(letaxWithdrawLogParam));
            Assert.isTrue(Objects.nonNull(serviceLetaxWithdrawLog), "不存在当前提现记录：" + withdrawalApply.getId());
            Assert.isTrue(serviceLetaxWithdrawLog.getIdCode().equals(idCode), "当前提现记录不是本人提现" + withdrawalApply.getId());
            Assert.isTrue(serviceLetaxWithdrawLog.getPlatformCode().equals(platformCode), "当前提现记录平台不正确" + withdrawalApply.getId());

            letaxWithdrawLogParam.setUpdatedAt(LocalDateTime.now());
            letaxWithdrawLogParam.setRemark("修改申请理由");
            letaxWithdrawLogParam.setReason(withdrawalApply.getReason());
            leTaxOneServiceImpl.updateAppleReasonDb(letaxWithdrawLogParam);
            return withdrawalApply.getId();
        }

        //自认证开始判断
        Assert.isTrue(serviceSelfCertificationWithdraw.getPlatformCode().equals(platformCode), "当前提现记录平台不正确" + withdrawalApply.getId());

        //更新数据
        selfCertificationWithdrawUp.setRemark("修改申请理由");
        selfCertificationWithdrawUp.setReason(0);
        selfCertificationWithdrawUp.setReasonNew(withdrawalApply.getReason());
        selfCertificationWithdrawUp.setUpdatedAt(LocalDateTime.now());
        //更新数据
        updateApplyReasonDb(selfCertificationWithdrawUp);
        return serviceSelfCertificationWithdraw.getId();
    }

    /**
     * 个体提现申请理由修改
     *
     * @param selfCertificationWithdrawUp selfCertificationWithdrawUp
     */
    public void updateApplyReasonDb(ServiceSelfCertificationWithdraw selfCertificationWithdrawUp) {
        serviceSelfCertificationWithdrawService.updateById(selfCertificationWithdrawUp);
    }

    /**
     * 自认证注册业务判断
     *
     * @param selfCertificationQuery
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void registered(SelfCertificationQuery selfCertificationQuery) {
        //账户类型
        CoverChargeEnum.ServiceAccountType accountType = CoverChargeEnum.ServiceAccountType.MANAGE_TYPE;
        selfCertificationQuery.setPlatformCode(accountType.getPlatform());

        ServiceAccount serviceAccount = serviceAccountService.getAccount(accountType.getCode(), selfCertificationQuery.getIdCode());
        Assert.notNull(serviceAccount.getId(), "该用户未创建账户");

        //判断税号是否被乐税注册个体户占用
        Integer companyNoNum = serviceLetaxRegisteredReturnService.queryTotal(selfCertificationQuery.getCompanyNo());
        Assert.isTrue(companyNoNum == 0, "该企业信息已经被使用");

        //查找是否已经认证过
        String isApplyStatus = SelfCertificationStatus.WAITING_APPROVED.getCode() + "," + SelfCertificationStatus.PASS.getCode() + "," + SelfCertificationStatus.REFUSE.getCode();

        //验证企业名称是否存在
        ServiceSelfCertification selfCertificationByCompanyName = serviceSelfCertificationMapper.queryBySearch(accountType.getPlatform(), null, selfCertificationQuery.getIdCode(), null, isApplyStatus, selfCertificationQuery.getCompanyName(), null);
        Assert.isTrue(selfCertificationByCompanyName == null, "该企业信息已经被使用");

        //验证企业代码|社会信用代码 (企业)是否存在
        ServiceSelfCertification selfCertificationByCompanyNo = serviceSelfCertificationMapper.queryBySearch(accountType.getPlatform(), null, selfCertificationQuery.getIdCode(), null, isApplyStatus, null, selfCertificationQuery.getCompanyNo());
        Assert.isTrue(selfCertificationByCompanyNo == null, "该企业信息已经被使用");

        selfCertificationQuery.setIdcardImage("");
        if (SelfCertificationTypeEnum.SINGLE.getCode().equals(selfCertificationQuery.getType())
                || IdentityTypeEnum.TYPE_B.getType().equals(selfCertificationQuery.getIdcardType())
                || IdentityTypeEnum.TYPE_C.getType().equals(selfCertificationQuery.getIdcardType())) {
            //个体工商户或者是港澳台身份证，校验身份证信息
            String upImageUrl = attachmentService.getUrl(selfCertificationQuery.getIdcardUpId());
            String downImageUrl = attachmentService.getUrl(selfCertificationQuery.getIdcardDownId());
            Assert.isTrue(StringUtils.isNotBlank(upImageUrl), "个体工商户或身份证图片无效");
            Assert.isTrue(StringUtils.isNotBlank(downImageUrl), "个体工商户或身份证图片无效");
            SelfCertificationIdcardImage selfCertificationIdcardImage = new SelfCertificationIdcardImage();
            selfCertificationIdcardImage.setDown_image(downImageUrl);
            selfCertificationIdcardImage.setUp_image(upImageUrl);
            JSONObject idcardImage = JSONObject.fromObject(selfCertificationIdcardImage);
            selfCertificationQuery.setIdcardImage(idcardImage.toString());
        }
        selfCertificationQuery.setBusinessImg(selfCertificationQuery.getBusinessImgId());
        selfCertificationQuery.setLicenceImg(selfCertificationQuery.getLicenceImgId());
        // todo 删除收款账户校验与手机校验逻辑 (DaMu)
        if (selfCertificationQuery.getIsRule().equals(SelfCertificationIsRuleEnum.REGISTER.getCode())) {
            ServiceSignQuery serviceSignInfo = serviceSignService.queryFirst(selfCertificationQuery.getIdCode(), accountType.getPlatform());
            ServiceSelfCertification selfCertificationInfo = serviceSelfCertificationMapper.queryBySearch(accountType.getPlatform(), selfCertificationQuery.getIdCode(), null, selfCertificationQuery.getType(), isApplyStatus, null, null);

            //调用数据库操作
            this.registeredUpdateOrInsert(selfCertificationQuery, serviceSignInfo, accountType, selfCertificationInfo);

            //通知会员和申请数字证书
            if (Objects.nonNull(selfCertificationInfo)
                    && SelfCertificationStatus.PASS.getCode().equals(selfCertificationInfo.getStatus())
                    && SignFromEnum.SERVICE_PROVIDER.getCode().equals(selfCertificationQuery.getFromType())) {
                try {
                    //通知会员
                    String bizId = String.valueOf(IdWorker.getId());
                    Integer userId = UserUtils.getUserId(selfCertificationQuery.getIdCode());
                    memberService.dealMemberAddStarAudit(bizId, selfCertificationQuery,
                            DateTimeUtils.localDateTimeToDate(selfCertificationInfo.getCheckAt()),
                            serviceSignInfo.getBeforeIdentity(), serviceSignInfo.getCurrentIdentity());

                    //申请数字证书
                    SelfCertificationQuery selfCertificationApplyCert = new SelfCertificationQuery();
                    selfCertificationApplyCert.setIdCode(selfCertificationQuery.getIdCode());
                    selfCertificationApplyCert.setType(selfCertificationInfo.getType());
                    selfCertificationApplyCert.setPlatformCode(selfCertificationInfo.getPlatformCode());
                    selfCertificationApplyCert.setIdcardType(selfCertificationInfo.getIdcardType());
                    selfCertificationApplyCert.setIdcardNo(selfCertificationQuery.getIdcardNo());
                    selfCertificationApplyCert.setIdcardName(selfCertificationQuery.getIdcardName());
                    selfCertificationApplyCert.setCompanyNo(selfCertificationInfo.getCompanyNo());
                    selfCertificationApplyCert.setCompanyName(selfCertificationInfo.getCompanyName());
                    selfCertificationApplyCert.setLegalMobile(selfCertificationQuery.getLegalMobile());
                    this.registeredApplyCert(selfCertificationApplyCert);
                } catch (CoverChargeException ce) {
                    throw new ServiceException(ce.getMsg());
                } catch (Exception e) {
                    log.error("申请证书或者通知会员报错", e);
                    throw new ServiceException("申请证书或者通知会员失败");
                }
            }
        }
    }

    /**
     * 自认证注册更新和新增
     *
     * @param selfCertificationQuery
     */
    public void registeredUpdateOrInsert(SelfCertificationQuery selfCertificationQuery, ServiceSignQuery serviceSignInfo, CoverChargeEnum.ServiceAccountType accountType, ServiceSelfCertification selfCertificationInfo) {
        //自认证拼接参数
        ServiceSelfCertification serviceSelfCertification = new ServiceSelfCertification();
        serviceSelfCertification.setIdCode(selfCertificationQuery.getIdCode());
        serviceSelfCertification.setPlatformCode(accountType.getPlatform());

        //获取账户
        ServiceAccount serviceAccount = serviceAccountService.getAccount(accountType.getCode(), selfCertificationQuery.getIdCode());
        serviceSelfCertification.setAccountId(serviceAccount.getId());
        serviceSelfCertification.setCompanyName(selfCertificationQuery.getCompanyName());
        serviceSelfCertification.setCompanyAddress(selfCertificationQuery.getCompanyAddress());
        serviceSelfCertification.setCompanyTel(selfCertificationQuery.getCompanyTel());
        serviceSelfCertification.setCompanyNo(selfCertificationQuery.getCompanyNo());
        serviceSelfCertification.setIdcardType(selfCertificationQuery.getIdcardType());
        serviceSelfCertification.setIdcardNo(selfCertificationQuery.getIdcardNo());
        serviceSelfCertification.setIdcardName(selfCertificationQuery.getIdcardName());
        serviceSelfCertification.setIdcardImage(selfCertificationQuery.getIdcardImage());
        serviceSelfCertification.setBankNo("");
        serviceSelfCertification.setCardHolder(selfCertificationQuery.getCardHolder());
        serviceSelfCertification.setBankName("");
        serviceSelfCertification.setBusinessImg(selfCertificationQuery.getBusinessImg());
        serviceSelfCertification.setLicenceImg(selfCertificationQuery.getLicenceImg());
        serviceSelfCertification.setType(selfCertificationQuery.getType());
        serviceSelfCertification.setIdcardName(selfCertificationQuery.getIdcardName().replaceAll(" ", ""));
        serviceSelfCertification.setLegalMobile(selfCertificationQuery.getLegalMobile().replaceAll(" ", ""));
        serviceSelfCertification.setUpdatedAt(LocalDateTime.now());

        //拼接更新和插入签约公共参数
        ServiceSign serviceSign = new ServiceSign();

        if (selfCertificationInfo != null) {//更新
            if (selfCertificationInfo.getStatus().equals(SelfCertificationStatus.REFUSE.getCode())) {
                serviceSelfCertification.setStatus(SelfCertificationStatus.WAITING_APPROVED.getCode());
            }

            //只要不是成功，则把isView置为第一次查看，这样成功后就可以弹窗
            if (!selfCertificationInfo.getStatus().equals(SelfCertificationStatus.PASS.getCode())) {
                serviceSign.setIsView(IsViewEnum.FIRST.getCode());
            }

            serviceSelfCertification.setId(selfCertificationInfo.getId());
            serviceSelfCertificationService.updateById(serviceSelfCertification);
        } else {//新增
            serviceSelfCertification.setCreatedAt(LocalDateTime.now());
            serviceSelfCertificationService.save(serviceSelfCertification);
            serviceSign.setIsView(IsViewEnum.FIRST.getCode());
        }

        //签约表操作
        String identification = SignIdentityEnum.certified_business.getCode();//默认企业
        String message = "自认证企业";//站内信发送标题
        if (selfCertificationQuery.getType().equals(SelfCertificationTypeEnum.SINGLE.getCode())) {//个体户
            identification = SignIdentityEnum.certified_individual.getCode();
            message = "自认证个体户";
        }
        String content = "您已完成【" + message + "】的合作方式签约，请查看合作方式说明，了解更多详情";//站内信发送内容

        //拼接更新和插入签约公共参数
        serviceSign.setIsSigned(IsSigndEnum.YES.getCode());
        serviceSign.setCurrentIdentity(identification);
        serviceSign.setHistoryIdentity(null);
        serviceSign.setSignTime(LocalDateTime.now().toString());
        serviceSign.setUpdatedTime(LocalDateTime.now().toString());

        //签约记录id
        Integer signId;
        if (serviceSignInfo != null) {//更新
            String beforeIdentification = serviceSignInfo.getCurrentIdentity();//默认为升级
            //判断不是升级操作
            if (serviceSignInfo.getCurrentIdentity().equals(SignIdentityEnum.certified_business.getCode()) || serviceSignInfo.getCurrentIdentity().equals(SignIdentityEnum.certified_individual.getCode())) {//不是升级
                beforeIdentification = serviceSignInfo.getBeforeIdentity();
            } else {//升级
                //更新签约记录表
                serviceSignRecordService.updateStatus(serviceSignInfo.getId(), SignFromEnum.SERVICE_PROVIDER.getCode());

                // 逻辑注销存管账户信息
                DepositoryAccount depositoryAccount = depositoryAccountRepository
                        .getByIdCodeStatusNormal(new UserIdCode(selfCertificationQuery.getIdCode()), DepositoryChannel.PING_AN);

                if (depositoryAccount != null) {

                    throw ApplicationException.error(ApplicationExceptionCode.DEP_ACCOUNT_OPENED);

                }

            }

            serviceSign.setBeforeIdentity(beforeIdentification);
            serviceSign.setId(serviceSignInfo.getId());
            serviceSignService.updateById(serviceSign);

            //更新之前的身份状态
            if (serviceSignInfo.getCurrentIdentity().equals(SignIdentityEnum.person.getCode())) {//个人
                serviceBankService.updateStatusToUnlink(selfCertificationQuery.getIdCode(), selfCertificationQuery.getPlatformCode());
            }
            if (serviceSignInfo.getCurrentIdentity().equals(SignIdentityEnum.regist_soho.getCode())) {//乐税注册个体户
                serviceLetaxRegisteredService.updateStatusToEnd(selfCertificationQuery.getIdCode(), selfCertificationQuery.getPlatformCode());
            }
            signId = serviceSignInfo.getId();
        } else {//新增，包含如果原先在星际有身份信息，那么来服务费升级身份，则新插入一条服务费签约信息和更新星际签约信息
            serviceSign.setBeforeIdentity(SignIdentityEnum.no_identity.getCode());
            serviceSign.setCreatedTime(LocalDateTime.now().toString());
            serviceSign.setIdCode(selfCertificationQuery.getIdCode());
            serviceSign.setPlatformCode(selfCertificationQuery.getPlatformCode());
            serviceSignService.save(serviceSign);
            signId = serviceSign.getId();
        }

        //插入签约记录表
        ServiceSignRecord serviceSignRecord = new ServiceSignRecord();
        serviceSignRecord.setCreatedTime(LocalDateTime.now().toString());
        serviceSignRecord.setUpdatedTime(LocalDateTime.now().toString());
        serviceSignRecord.setSignId(signId);
        serviceSignRecord.setSignFrom(SignFromEnum.getFromCode(selfCertificationQuery.getFromType()));
        serviceSignRecord.setStatus(SignRecordStatusEnum.VALID.getCode());
        serviceSignRecordService.save(serviceSignRecord);

        //发送站内信
//        if (selfCertificationInfo != null && selfCertificationInfo.getStatus().equals(SelfCertificationStatus.PASS.getCode()) && selfCertificationQuery.getPlatformCode().equals(CoverChargeEnum.ServiceAccountType.CUSTOMER_TYPE.getDesc())) {
//            userMessageClient.sendDtServiceFeeMessage(selfCertificationInfo.getIdCode(), "【签约通知】",
//                    content, true, true, false);
//        }
    }

    /**
     * 异步申请证书
     *
     * @param selfCertificationQuery
     */
    @Override
    public void registeredApplyCert(SelfCertificationQuery selfCertificationQuery) {
        SignContractReqVo signContractReqVo = new SignContractReqVo();
        signContractReqVo.setType(selfCertificationQuery.getType());
        log.info("申请证书开始：{}", selfCertificationQuery.toString());
        //判断用户证书是否需要申请证书
        if (!serviceContractService.checkCert(selfCertificationQuery.getPlatformCode(),
                selfCertificationQuery.getIdCode(), signContractReqVo, selfCertificationQuery.getIdcardNo(),
                selfCertificationQuery.getCompanyNo(), Boolean.FALSE)) {
            log.info("申请证书通过校验开始：{}", selfCertificationQuery.toString());
            ApplyCertificateReqVo applyCertificateReqVo = new ApplyCertificateReqVo();
            //法人身份证号-MD5申请证书
            applyCertificateReqVo.setAccount(MD5Utils.MD5Encode(selfCertificationQuery.getIdcardNo()));
            applyCertificateReqVo.setApplyCert(SelfCertificationApplyTypeEnum.YES.getCode().toString());
            applyCertificateReqVo.setUserType(ContractUserTypeEnum.SINGLE);

            PersonCertApplyVo personCertApplyVo = new PersonCertApplyVo();
            personCertApplyVo.setName(selfCertificationQuery.getIdcardName());
            personCertApplyVo.setIdentity(selfCertificationQuery.getIdcardNo());
            personCertApplyVo.setIdentityType(IdentityTypeEnum.get(selfCertificationQuery.getIdcardType()));
            applyCertificateReqVo.setPerson(personCertApplyVo);
            //个人申请证书
            log.info("个人申请证书开始");
            serviceContractService.applyCertificate(selfCertificationQuery.getPlatformCode(),
                    selfCertificationQuery.getIdCode(), selfCertificationQuery.getType(), applyCertificateReqVo);
            log.info("个人申请证书结束");
            //企业
            //企业信用代码-MD5申请证书
            applyCertificateReqVo.setAccount(MD5Utils.MD5Encode(selfCertificationQuery.getCompanyNo()));
            applyCertificateReqVo.setUserType(ContractUserTypeEnum.COMPANY);

            CompanyCertApplyVo companyCertApplyVo = new CompanyCertApplyVo();
            companyCertApplyVo.setName(selfCertificationQuery.getCompanyName());
            companyCertApplyVo.setRegCode(selfCertificationQuery.getCompanyNo());
            companyCertApplyVo.setLegalPerson(selfCertificationQuery.getIdcardName());
            companyCertApplyVo.setLegalPersonIdentity(selfCertificationQuery.getIdcardNo());
            companyCertApplyVo.setLegalPersonIdentityType(IdentityTypeEnum.get(selfCertificationQuery.getIdcardType()));
            companyCertApplyVo.setLegalPersonMobile(selfCertificationQuery.getLegalMobile());
            applyCertificateReqVo.setCompany(companyCertApplyVo);
            //企业申请证书
            log.info("企业申请证书开始");
            serviceContractService.applyCertificate(selfCertificationQuery.getPlatformCode(),
                    selfCertificationQuery.getIdCode(), selfCertificationQuery.getType(), applyCertificateReqVo);
            log.info("企业申请证书结束");
        }
    }

    /**
     * 自认证查询
     *
     * @param selfCertificationQuery
     */
    @Override
    public ServiceSelfCertification registeredInfo(SelfCertificationQuery selfCertificationQuery) {
        //账户类型
        CoverChargeEnum.ServiceAccountType accountType = CoverChargeEnum.ServiceAccountType.MANAGE_TYPE;

        String isApplyStatus = SelfCertificationStatus.WAITING_APPROVED.getCode() + "," + SelfCertificationStatus.PASS.getCode() + "," + SelfCertificationStatus.REFUSE.getCode();
        ServiceSelfCertification selfCertification = serviceSelfCertificationMapper.queryBySearch(accountType.getPlatform(), selfCertificationQuery.getIdCode(), null, null, isApplyStatus, null, null);
        Assert.isTrue(selfCertification != null, "该代理暂无认证信息");
        return selfCertification;
    }

    /**
     * 区域服务商判断需不需要升级
     *
     * @param selfCertificationQuery
     */
    @Override
    public Integer registeredUpgrade(SelfCertificationQuery selfCertificationQuery) {
        Integer registeredUpgradeStatus = ServiceProviderIsUpgradeEnum.NOT_UPGRADE.getCode();//默认不需要升级
        if (SignFromEnum.SERVICE_PROVIDER.getCode().equals(selfCertificationQuery.getFromType())) {//如果来自区域服务商就判断的
            //账户类型
            CoverChargeEnum.ServiceAccountType accountType = CoverChargeEnum.ServiceAccountType.MANAGE_TYPE;

            ServiceSign serviceSignParam = new ServiceSign();
            serviceSignParam.setIdCode(selfCertificationQuery.getIdCode());
            serviceSignParam.setPlatformCode(accountType.getPlatform());
            ServiceSign serviceSign = serviceSignService.getOne(new QueryWrapper<>(serviceSignParam));
            if (serviceSign != null && CoverChargeEnum.CommonStatus.YES.getName().equals(serviceSign.getIsSigned())) {//签约了
                registeredUpgradeStatus = ServiceProviderIsUpgradeEnum.IS_UPGRADE.getCode();
            }
        }
        return registeredUpgradeStatus;
    }

    /**
     * 手机三要素获取验证码
     *
     * @param smsVerification
     */
    @Override
    public String doIdentity3Auth(SmsVerification smsVerification, boolean needGeetest) {

        if (needGeetest) {
            //极验校验
            ManMachineValidateData manMachineValidateData = new ManMachineValidateData(smsVerification.getChallenge(),
                    smsVerification.getValidate(),
                    smsVerification.getSecCode());
            boolean geetestCheckResult = smsBaseService.manMachineVerification(manMachineValidateData);
            if (!geetestCheckResult) {
                throw ApplicationException.error(ApplicationExceptionCode.GEETEST_CHECK_FAIL);
            }
        }

        if (IdentityTypeEnum.TYPE_B.getType().equals(smsVerification.getIdCardType())
                || IdentityTypeEnum.TYPE_C.getType().equals(smsVerification.getIdCardType())) {
            // 港澳台用户发送验证码
            SendSmsVerifyCodeData sendSmsVerifyCodeData = new SendSmsVerifyCodeData(
                    "+86",
                    smsVerification.getMobile(),
                    UserType.USER,
                    OperationType.SELF_CERTIFICATION,
                    null, null, null);
            smsVerifyCodeService.sendSmsVerifyCode(sendSmsVerifyCodeData, false);
            return "success";
        } else {
            // 非港澳台用户，上上签用户验证并发送验证码
            String bizId = String.valueOf(IdWorker.getId());

            SmsVerificationReq smsVerificationReq = new SmsVerificationReq();
            smsVerificationReq.setName(smsVerification.getName());
            smsVerificationReq.setIdCardType(smsVerification.getIdCardType());
            smsVerificationReq.setIdCardNo(smsVerification.getIdCardNo());
            smsVerificationReq.setMobile(smsVerification.getMobile());

            String doIdentity3AuthResult = authService.doIdentity3Auth(bizId, smsVerificationReq);
            JSONObject resultData = JSONObject.fromObject(doIdentity3AuthResult);
            Assert.isTrue(resultData.getString("result").equals(SignThirdReturnCode.SUCCESS.getCode()), this.getReturnMsg(resultData.getString("msg")));
            return resultData.getString("personalIdentity3Key");
        }
    }

    /**
     * 个人手机号三要素校验
     *
     * @param smsVerificationVerifyReq
     */
    @Override
    public void doIdentity3AuthVerify(SmsVerificationVerifyReq smsVerificationVerifyReq) {
        log.info("个人手机号三要素校验请求验证码：code:{}", smsVerificationVerifyReq.getVcode());
        String bizId = String.valueOf(IdWorker.getId());
        String result = authService.doIdentity3AuthVerify(bizId, smsVerificationVerifyReq);
        JSONObject resultData = JSONObject.fromObject(result);
        log.info("个人手机号三要素校验结果返回：bizId:{},resultData{}", bizId, resultData.toString());
        Assert.isTrue(resultData.getString("result").equals(SignThirdReturnCode.SUCCESS.getCode()), this.getReturnMsg(resultData.getString("msg")));
    }

    /**
     * 通知会员认证成功
     *
     * @param selfCertificationQuery
     */
    @Override
    public Boolean noticeStarService(SelfCertificationQuery selfCertificationQuery) {
        log.info("[MQ认证成功通知会员]:Query{},checkAt{}", selfCertificationQuery, DateTimeUtils.localDateTimeToDate(selfCertificationQuery.getCheckAt()));
        String bizId = String.valueOf(IdWorker.getId());
        memberService.dealMemberAddStarAudit(bizId, selfCertificationQuery, DateTimeUtils.localDateTimeToDate(selfCertificationQuery.getCheckAt()), selfCertificationQuery.getBeforeIdentity(), selfCertificationQuery.getCurrentIdentity());
        return true;
    }

    /**
     * 返回通知信息
     * */
    /**
     * 通知会员认证成功
     *
     * @param msg
     */
    public String getReturnMsg(String msg) {
        CertificateApplyEnum certificateApplyEnum = CertificateApplyEnum.getStatusDesc(msg);
        if (!Objects.isNull(certificateApplyEnum)) {
            msg = certificateApplyEnum.getDesc();
        }
        return msg;
    }
}
